<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">

<head>
    <meta name="viewport" content="width=device-width" charset="utf-8" />
    <title>RateFee</title>
</head>

<body>
    <input id="input" onchange="_clear_()" type="text" style="display: block; width: 100%; line-height: 1.6;" data-value='{"AgencyId":"","FeeAmountType":"","FeeCustomType":"","FenQiType":0,"HandRate":10,"IsPay":true,"Month":12,"PayDefault":0,"PayFeeCut":0.1,"PayRate":10,"PayType":1,"ProtocolUrl":"","TopStagingNum":3,"YearRate":"10","PayTopStagingNum":12,"amount":1000}'>
    <button id="button" onclick="_cal_()" style="display: block; margin: 1em auto; padding: 0.3em 1em;">计算</button>
    <textarea id="textarea" rows="20" style="display: block; width: 100%; resize: vertical;"></textarea>

    <script>
        function _jsonFmt_(jsonStr) {
            var t = [];
            var tab = 0;
            var inString = false;
            var rPad = function (str, len, char) {
                return str + Array(Math.max((len || 0) - str.toString().length, 0) + 1).join(char || '');
            };
            for (var i = 0, len = jsonStr.length; i < len; i++) {
                var c = jsonStr.charAt(i);
                if (inString && c === inString) {
                    if (jsonStr.charAt(i - 1) !== '\\') {
                        inString = false;
                    }
                } else if (!inString && (c === '"' || c === '\'')) {
                    inString = c;
                } else if (!inString && (c === ' ' || c === '\t')) {
                    c = '';
                } else if (!inString && c === ':') {
                    c += ' ';
                } else if (!inString && c === ',') {
                    c += rPad('\n', tab * 2 + 1, ' ');
                } else if (!inString && (c === '[' || c === '{')) {
                    tab++;
                    c += rPad('\n', tab * 2 + 1, ' ');
                } else if (!inString && (c === ']' || c === '}')) {
                    tab--;
                    c = rPad('\n', tab * 2 + 1, ' ') + c;
                }
                t.push(c);
            }
            return t.join('');
        }
        function _cal_() {
            var jsonStr = document.querySelector('#input').value;
            document.querySelector('#textarea').value = _jsonFmt_(calresult(jsonStr));
        }
        function _clear_() {
            document.querySelector('#textarea').value = '';
        }
    </script>
    <script type="text/javascript">
        (function () {
            var equityPack = {
                init: function () {

                },
                xxxx: function () {

                }
            };
            var floatObj = window.ComputeObj = function () {

                /*
                 * 判断obj是否为一个整数
                 */
                function isInteger(obj) {
                    return Math.floor(obj) === obj
                }

                /*
                 * 将一个浮点数转成整数，返回整数和倍数。如 3.14 >> 314，倍数是 100
                 * @param floatNum {number} 小数
                 * @return {object}
                 *   {times:100, num: 314}
                 */
                function toInteger(floatNum) {
                    var ret = { times: 1, num: 0 }
                    var isNegative = floatNum < 0
                    if (isInteger(floatNum)) {
                        ret.num = floatNum
                        return ret
                    }
                    var strfi = floatNum + ''
                    var dotPos = strfi.indexOf('.')
                    var len = strfi.substr(dotPos + 1).length
                    var times = Math.pow(10, len)
                    var intNum = parseInt(Math.abs(floatNum) * times + 0.5, 10)
                    ret.times = times
                    if (isNegative) {
                        intNum = -intNum
                    }
                    ret.num = intNum
                    return ret
                }

                /*
                 * 核心方法，实现加减乘除运算，确保不丢失精度
                 * 思路：把小数放大为整数（乘），进行算术运算，再缩小为小数（除）
                 *
                 * @param a {number} 运算数1
                 * @param b {number} 运算数2
                 * @param digits {number} 精度，保留的小数点数，比如 2, 即保留为两位小数
                 * @param op {string} 运算类型，有加减乘除（add/subtract/multiply/divide）
                 *
                 */
                function operation(a, b, digits, op) {
                    var o1 = toInteger(a)
                    var o2 = toInteger(b)
                    var n1 = o1.num
                    var n2 = o2.num
                    var t1 = o1.times
                    var t2 = o2.times
                    var max = t1 > t2 ? t1 : t2
                    var result = null
                    switch (op) {
                        case 'add':
                            if (t1 === t2) { // 两个小数位数相同
                                result = n1 + n2
                            } else if (t1 > t2) { // o1 小数位 大于 o2
                                result = n1 + n2 * (t1 / t2)
                            } else { // o1 小数位 小于 o2
                                result = n1 * (t2 / t1) + n2
                            }
                            return result / max
                        case 'subtract':
                            if (t1 === t2) {
                                result = n1 - n2
                            } else if (t1 > t2) {
                                result = n1 - n2 * (t1 / t2)
                            } else {
                                result = n1 * (t2 / t1) - n2
                            }
                            return result / max
                        case 'multiply':
                            result = (n1 * n2) / (t1 * t2)
                            return result
                        case 'divide':
                            if (n1 == 0 || n2 == 0) {
                                return 0;
                            } else {
                                result = (n1 / n2) * (t2 / t1)
                                return result
                            }

                    }
                }

                // 加减乘除的四个接口
                function add(a, b, digits) {
                    return operation(a, b, digits, 'add')
                }
                function subtract(a, b, digits) {
                    return operation(a, b, digits, 'subtract')
                }
                function multiply(a, b, digits) {
                    return operation(a, b, digits, 'multiply')
                }
                function divide(a, b, digits) {
                    return operation(a, b, digits, 'divide')
                }

                // exports
                return {
                    add: add,
                    subtract: subtract,
                    multiply: multiply,
                    divide: divide
                }
            }();
            /* utils*/
            var utils = window.PpdRate = {},
                fenqienum = {
                    all: 0,
                    pay: 1,
                    hand: 2
                };

            utils.type = function (o) {//判断对象类型
                return Object.prototype.toString.call(o).slice(8, -1).toLowerCase();
            };

            utils.round = function (n) {//把n转换成浮点数
                return parseFloat(n * 1e12) / 1e12;
            };

            utils.toJson = function (str) {//如果可以，则转换成JSON对象，否则计算结果
                if (JSON.parse) {
                    return JSON.parse(str);
                }

                return eval('(' + str + ')');
            };

            utils.formatObj = function (str, obj) {//匹配：  用obj下标为b的字符串替换所有 {多个（1字母1数字）组合}
                return str.replace(/\{([a-z\d]+)\}/ig, function (a, b) { return obj[b]; });
            };
            utils.compute = function (f) {
                var digit = 20;
                var m = Math.pow(10, digit);
                return parseInt(f * m, 10) / m;
            }
            utils.formatNum = function (n) {//输出形如1.12的数字，舍去小数点第三位及其以后的东西
                var r = n + '';
                if (r.indexOf('.') === -1) {
                    return r + '.00';
                }

                var arr = r.split('.');
                return arr[0] + '.' + (arr[1] + '00').substring(0, 2);
            };

            utils.formatNum2 = function (n) {//是0就不用变成0.00
                return parseFloat(utils.formatNum(n));
            };

            utils.formatDate = function (date, fmt) {//格式化日期
                var o = {
                    "M+": date.getMonth() + 1,
                    "d+": date.getDate(),
                    "h+": date.getHours(),
                    "m+": date.getMinutes(),
                    "s+": date.getSeconds(),
                    "q+": Math.floor((date.getMonth() + 3) / 3),
                    "S": date.getMilliseconds()
                };
                if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length));
                for (var k in o)
                    if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
                return fmt;
            };

            utils.calfee = function (amount, month, yearRate, handRate, payRate, payType, isPay, fenqiType, clientCode, payCutFeeRatio, topNum, payNum) {//如果有分期类型，则调用calall()，如果没有，则
                amount = parseFloat(amount) || 0;
                month = parseInt(month) || 0;
                yearRate = parseFloat(yearRate) || 0;
                handRate = parseFloat(handRate) || 0;
                payRate = parseFloat(payRate) || 0;
                payType = parseInt(payType) || 0;
                if (isPay == 1) {
                    isPay = 1;
                } else {
                    isPay = 0;
                }
                fenqiType = parseInt(fenqiType) || 0;
                clientCode = parseInt(clientCode) || 0;
                var args = [amount, month, yearRate, handRate, payRate, payType, isPay, fenqiType, clientCode, payCutFeeRatio, topNum, payNum];
                var result = {};

                switch (fenqiType) {
                    case fenqienum.all:
                        result = calall.apply(this, args);
                        break;
                    case fenqienum.pay:
                        result = calpay.apply(this, args);
                        break;
                    case fenqienum.hand:
                        result = calhand.apply(this, args);
                        break;
                    default:
                        result = callother.apply(this, args);
                        break;
                }

                result.balance = utils.formatNum2(result.balance);
                result.MonthRate = getMonthRate(yearRate);

                return result;
            };
            function getMonthRate(yearRate) {
                return floatObj.divide(yearRate, 1200);
            }
            function debx(amount, yearRate, month) {//等额本息
                var monthRate = getMonthRate(yearRate), p = parseFloat(Math.pow(1 + monthRate, month));
                //amount * monthRate * p / (p - 1);
                return floatObj.divide(floatObj.multiply(amount, floatObj.multiply(monthRate, p)), (p - 1));
            };

            function getHandFee(amount, handRate) {//返回handRate%*amount；这个handRate是百分比前面的数字
                //(handRate / 100) * amount
                return utils.formatNum2(floatObj.divide(floatObj.multiply(handRate, amount), 100));
            }

            function getPayFee(amount, payRate) {
                //(payRate / 100) * amount
                return utils.formatNum2(floatObj.divide(floatObj.multiply(payRate, amount), 100));
            }
            function monthlyPayListOther(amount, month, yearRate, handRate, payRate, topNum, fenqiType, bx) {
                var cinterest = 0, ccapital = 0;
                var mPayList = new Array();
                var remainAmount = amount;
                var monthRate = getMonthRate(yearRate);
                var bxf = utils.formatNum2(bx);
                for (var m = 1; m <= month; m++) {
                    //cinterest=remainAmount * yearRate / 12 / 100
                    cinterest = floatObj.multiply(remainAmount, monthRate);
                    //bx - remainAmount * yearRate / 12 / 100
                    ccapital = floatObj.subtract(bx, cinterest);
                    mPayList.push({
                        payMonth: m,
                        interest: utils.formatNum2(cinterest),
                        interestLabel: "利息:",
                        capital: utils.formatNum2(floatObj.subtract(bxf, utils.formatNum2(cinterest))),
                        capitalLabel: "本金:",
                        totalLabel: '',// TODO '应还'
                        total: bxf,
                        deadlineDate: getDeadlineDate(m),
                        serviceChargeMessage: '拍拍贷为借款人提供服务，向借款人收取的费用。',
                        guaranteeFeeMessage: '风险保障费是由参与风险保障计划的借款人按照风险保障计划文件约定向风险保障金专项账户缴纳的，用于补偿参加本计划的借款人根据风险保障计划文件应当向所对应的出借人支付潜在回款损失的保障费用。服务费是第三方依照风险保障计划提供服务向参与本计划的借款人收取的费用。'
                    });
                    remainAmount = floatObj.subtract(remainAmount, ccapital);
                }
                return mPayList;
            }
            //全不分期
            function callother(amount, month, yearRate, handRate, payRate, payType, isPay, fenqiType, clientCode, payCutFeeRatio, topNum, payNum) {
                var bx = debx(amount, yearRate, month);
                var handfee = getHandFee(amount, handRate);
                var payfee = getPayFee(amount, payRate);
                if (payType != 1) payfee = 0;
                var balance = floatObj.subtract(amount, floatObj.add(handfee, payfee));

                return {
                    monthlyPayment: utils.formatNum2(bx),
                    monthlyPaymentLabel: "每月还款",
                    balance: utils.formatNum2(balance),
                    balanceLabel: "实际到账",
                    mPayList: monthlyPayListOther(amount, month, yearRate, handRate, payRate, topNum, fenqiType, bx),
                    payCutFee: utils.formatNum2(payfee),
                    payCutFeeLabel: '风险保障及服务费:',
                    handFee: handfee,
                    handFeeLabel: '服务费:'
                }
            }
            /**
            * 每月偿还明细列表
            **/
            function monthlyPayList(amount, month, yearRate, handRate, payRate, handfee, payfee, topNum, fenqiType, bx, payNum) {
                var monthRate = getMonthRate(yearRate);
                var mPayList = new Array();
                var remainAmount = amount;
                var cinterest = 0, ccapital = 0, cserviceCharge = 0, cguaranteeFee = 0;//利息，本金，服务费，风险保障及服务费
                for (var m = 1; m <= month; m++) {
                    cinterest = 0; ccapital = 0; cserviceCharge = 0; cguaranteeFee = 0;
                    //cinterest=remainAmount * yearRate / 12 / 100
                    cinterest = floatObj.multiply(remainAmount, monthRate);
                    //bx - remainAmount * yearRate / 12 / 100
                    ccapital = floatObj.subtract(bx, cinterest);
                    if (fenqiType == 0 || fenqiType == 2) {//全分期，手续分期
                        if (m <= topNum) {//在付手续费
                            cserviceCharge = floatObj.divide(handfee, topNum);
                        } else {//手续费付完了
                            cserviceCharge = 0;
                        }
                    } else {
                        cserviceCharge = 0;
                    }
                    if (fenqiType == 0 || fenqiType == 1) {//加赔分期,全分期
                        if (m <= payNum) {
                            cguaranteeFee = floatObj.divide(payfee, payNum);
                        } else {
                            cguaranteeFee = 0.00;
                        }
                    } else {
                        cguaranteeFee = 0.00;
                    }
                    //cinterest + ccapital + cserviceCharge + cguaranteeFee
                    var t = utils.formatNum2(floatObj.add(bx, floatObj.add(cserviceCharge, cguaranteeFee)));
                    mPayList.push({
                        payMonth: m,
                        interest: utils.formatNum2(cinterest),
                        interestLabel: "利息:",
                        capital: utils.formatNum2(floatObj.subtract(bx, utils.formatNum2(cinterest))),
                        capitalLabel: "本金:",
                        serviceCharge: utils.formatNum2(cserviceCharge),
                        serviceChargeLabel: "服务费:",
                        guaranteeFee: utils.formatNum2(cguaranteeFee),
                        guaranteeFeeLabel: "风险保障及服务费:",
                        totalLabel: '',// TODO '应还'
                        total: utils.formatNum2(t),
                        deadlineDate: getDeadlineDate(m),
                        serviceChargeMessage: '拍拍贷为借款人提供服务，向借款人收取的费用。',
                        guaranteeFeeMessage: '风险保障费是由参与风险保障计划的借款人按照风险保障计划文件约定向风险保障金专项账户缴纳的，用于补偿参加本计划的借款人根据风险保障计划文件应当向所对应的出借人支付潜在回款损失的保障费用。服务费是第三方依照风险保障计划提供服务向参与本计划的借款人收取的费用。'
                    })
                    remainAmount = floatObj.subtract(remainAmount, ccapital);
                }
                return mPayList;
            }

            //全分期，加赔费和手续费分期期数一定相等，
            function calall(amount, month, yearRate, handRate, payRate, payType, isPay, fenqiType, clientCode, payCutFeeRatio, topNum, payNum) {
                var bx = debx(amount, yearRate, month),
                    handfee = getHandFee(amount, handRate),
                    pay = payType === 1 || isPay === 1,
                    //payfee = pay ? (amount * (payRate / 100)) : 0,
                    payfee = pay ? utils.formatNum2(floatObj.multiply(amount, floatObj.divide(payRate, 100))) : 0,
                    payCutFee = 0;

                if (pay && payCutFeeRatio > 0) {
                    payCutFee = floatObj.multiply(payfee, payCutFeeRatio);
                    payfee = floatObj.subtract(payfee, payCutFee);
                }
                var mPayList = monthlyPayList(amount, month, yearRate, handRate, payRate, handfee, payfee, topNum, fenqiType, bx, payNum);
                if ((topNum && topNum > 0 && topNum < month) || (payNum && payNum > 0 && payNum < month)) {
                    var payone = floatObj.divide(payfee, payNum);
                    //var a = utils.formatNum2(bx) + utils.formatNum2(handfee / topNum) + payone;
                    var a = utils.formatNum2(floatObj.add(bx, floatObj.add(floatObj.divide(handfee, topNum), payone))).toFixed(2);//服务费+赔费
                    var ji = 1;
                    if (topNum && topNum > 0 && topNum < month) {
                        ji = topNum + 1;
                    } else {
                        ji = payNum + 1;
                    }
                    var b = mPayList[ji - 1].total.toFixed(2);//服务费,赔费付完了

                    return {
                        FeeType: 2,
                        num: topNum,
                        monthlyPayment: "￥" + a + '（第' + ji + "期起月还" + "￥" + b + "）",
                        monthlyPaymentLabel: "每月还款",
                        balance: utils.formatNum2(floatObj.subtract(amount, payCutFee)),
                        balanceLabel: "实际到账",
                        payCutFee: utils.formatNum2(payCutFee),
                        payCutFeeLabel: '风险保障及服务费:',
                        handFee: 0,
                        handFeeLabel: '服务费:',
                        mPayList: mPayList
                    };
                } else {
                    //utils.formatNum2(bx) + utils.formatNum2((handfee + payfee) / month)
                    var c = floatObj.add(bx, floatObj.divide(floatObj.add(handfee, payfee), month));
                    bx = utils.round(utils.formatNum2(c).toFixed(2));
                    return {
                        monthlyPayment: "￥" + bx,
                        monthlyPaymentLabel: "每月还款",
                        //amount - utils.formatNum2(payCutFee)
                        balance: utils.formatNum2(floatObj.subtract(amount, payCutFee)),
                        balanceLabel: "实际到账",
                        payCutFee: utils.formatNum2(payCutFee),
                        payCutFeeLabel: '风险保障及服务费:',
                        handFee: 0,
                        handFeeLabel: '服务费:',
                        mPayList: mPayList
                    };
                }
            }
            //加赔分期，手续费一次付清
            function calpay(amount, month, yearRate, handRate, payRate, payType, isPay, fenqiType, clientCode, payCutFeeRatio, topNum, payNum) {
                //payfee = amount * (payRate / 100)
                var bx = debx(amount, yearRate, month),
                    payfee = floatObj.multiply(amount, floatObj.divide(payRate, 100)),
                    handfee = getHandFee(amount, handRate),
                    payCutFee = 0, mp = 0;
                if (payType === 1 || isPay === 1) {
                    if (payCutFeeRatio > 0) {
                        payCutFee = floatObj.multiply(payfee, payCutFeeRatio);
                        payfee = floatObj.subtract(payfee, payCutFee);
                    }
                    if (payNum && payNum > 0 && payNum < month) {//加赔费提前还
                        mp = utils.formatNum2(floatObj.add(bx, floatObj.divide(payfee, payNum)));
                        var ji = payNum + 1;
                        mp = mp + '（第' + ji + "期起月还" + "￥" + utils.formatNum2(bx).toFixed(2) + "）"
                    } else {
                        mp = utils.formatNum2(floatObj.add(bx, floatObj.divide(payfee, month))).toFixed(2);
                    }

                } else {
                    payfee = 0;
                    payCutFee = 0;
                }
                var mPayList = monthlyPayList(amount, month, yearRate, handRate, payRate, handfee, payfee, topNum, fenqiType, bx, payNum);
                return {
                    //mp = utils.round(utils.formatNum2(bx) + utils.formatNum2(payfee / month));
                    monthlyPayment: "￥" + ((mp && mp != 0) ? mp : utils.formatNum2(bx).toFixed(2)),
                    monthlyPaymentLabel: "每月还款",
                    // balance: utils.formatNum2(amount - utils.formatNum2(handfee) - utils.formatNum2(payCutFee))
                    balance: utils.formatNum2(floatObj.subtract(amount, floatObj.add(handfee, payCutFee))),
                    balanceLabel: '实际到账',
                    payCutFee: utils.formatNum2(payCutFee),
                    payCutFeeLabel: '风险保障及服务费:',
                    handFee: utils.formatNum2(handfee),
                    handFeeLabel: '服务费:',
                    mPayList: mPayList
                };
            }
            //手续分期，加赔费一次收
            function calhand(amount, month, yearRate, handRate, payRate, payType, isPay, fenqiType, clientCode, payCutFeeRatio, topNum, payNum) {
                var bx = debx(amount, yearRate, month),
                    handfee = getHandFee(amount, handRate),
                    payfee = getPayFee(amount, payRate);
                if (payType != 1) payfee = 0;
                var mPayList = monthlyPayList(amount, month, yearRate, handRate, payRate, handfee, payfee, topNum, fenqiType, bx, payNum);
                if (topNum && topNum > 0 && topNum < month) {
                    //var a = utils.formatNum2(bx) + utils.formatNum2(handfee / topNum);
                    var a = utils.formatNum2(floatObj.add(bx, floatObj.divide(handfee, topNum))).toFixed(2);
                    var b = utils.formatNum2(utils.round(bx)).toFixed(2);
                    var ji = topNum + 1;
                    return {
                        FeeType: 2,
                        monthlyPayment: "￥" + a + '（第' + ji + "期起月还" + "￥" + b + "）",
                        monthlyPaymentLabel: "每月还款",
                        num: topNum,
                        //amount - payfee
                        balance: utils.formatNum2(floatObj.subtract(amount, payfee)),
                        balanceLabel: '实际到账',
                        payCutFee: utils.formatNum2(payfee),
                        payCutFeeLabel: '风险保障及服务费:',
                        handFee: 0,
                        handFeeLabel: '服务费:',
                        mPayList: mPayList
                    };
                } else {
                    //var c = utils.formatNum2(bx) + utils.formatNum2(handfee / month);
                    var c = utils.formatNum2(floatObj.add(bx, floatObj.divide(handfee, month)));
                    return {
                        monthlyPayment: "￥" + utils.round(c).toFixed(2),
                        monthlyPaymentLabel: "每月还款",
                        //amount -payfee
                        balance: utils.formatNum2(floatObj.subtract(amount, payfee)),
                        balanceLabel: '实际到账',
                        payCutFee: utils.formatNum2(payfee),
                        payCutFeeLabel: '风险保障及服务费:',
                        handFee: 0,
                        handFeeLabel: '服务费:',
                        mPayList: mPayList
                    };
                }
            }
            utils.correctPenny = function (amount, resultObj) {//一分钱纠正
                var hfm = resultObj.handFee;
                if (!hfm) hfm = 0;
                var pfm = resultObj.payCutFee;
                if (!pfm) pfm = 0;
                var resmain = floatObj.add(resultObj.balance, floatObj.add(hfm, pfm));
                var pennymain = floatObj.subtract(amount, resmain);
                if (resultObj.handFee && resultObj.handFee != 0) {
                    resultObj.handFee = floatObj.add(resultObj.handFee, pennymain);
                } else if (resultObj.payCutFee && resultObj.payCutFee != 0) {
                    resultObj.payCutFee = floatObj.add(resultObj.payCutFee, pennymain);
                }
                resultObj.mPayList.map(function (mpl) {
                    var gf = (mpl.guaranteeFee && mpl.guaranteeFee != 0) ? mpl.guaranteeFee : 0;
                    var sc = (mpl.serviceCharge && mpl.serviceCharge != 0) ? mpl.serviceCharge : 0;
                    //var res=mpl.interest+mpl.capital+mpl.guaranteeFee+mpl.serviceCharge;
                    var res = floatObj.add(mpl.interest, floatObj.add(mpl.capital, floatObj.add(gf, sc)));
                    var penny = floatObj.subtract(mpl.total, res);
                    if (mpl.guaranteeFee && mpl.guaranteeFee != 0) {
                        mpl.guaranteeFee = floatObj.add(mpl.guaranteeFee, penny);
                    } else if (mpl.serviceCharge && mpl.serviceCharge != 0) {
                        mpl.serviceCharge = floatObj.add(mpl.serviceCharge, penny);
                    } else if (mpl.interest && mpl.interest != 0) {
                        mpl.interest = floatObj.add(mpl.interest, penny);
                    }
                })

            }
        })(window, undefined);

        function getDateList(m) {
            var nowDate = new Date(),
                todayNum = nowDate.getDate(),
                year = nowDate.getFullYear(),
                month = nowDate.getMonth() + 1,
                arr = [], crtMonthMaxDay;

            for (var index = 1; index <= m; index++) {
                month++;
                if (month > 12) {
                    year++;
                    month = 1;
                }

                switch (month) {
                    case 2:
                        crtMonthMaxDay = isLeapYear(year) ? 29 : 28;
                        break;
                    case 1:
                    case 3:
                    case 5:
                    case 7:
                    case 8:
                    case 10:
                    case 12:
                        crtMonthMaxDay = 31;
                        break;
                    default:
                        crtMonthMaxDay = 30;
                        break;
                }
                var dateNum = todayNum <= crtMonthMaxDay ? todayNum : crtMonthMaxDay;
                arr.push(year + '.' + month + '.' + (dateNum < 10 ? ('0' + dateNum) : dateNum));
            }

            return arr;
        }

        function getDeadlineDate(mNum) {
            var lPad = function (str, len, char) {
                return Array(Math.max((len || 0) - str.toString().length, 0) + 1).join(char || '') + str;
            };
            //now
            var _dt = new Date();
            var _dtArr = [
                _dt.getFullYear(),
                _dt.getMonth(),
                _dt.getDate()
            ];
            //target
            var res = new Date(_dtArr[0], _dtArr[1] + mNum, _dtArr[2]);
            var resArr = [
                res.getFullYear(),
                res.getMonth(),
                res.getDate()
            ];
            return [
                resArr[0],
                lPad(resArr[2] === _dtArr[2] ? resArr[1] + 1 : resArr[1], 2, '0'),
                lPad(resArr[2] === _dtArr[2] ? resArr[2] : new Date(_dtArr[0], _dtArr[1] + mNum + 1, -1).getDate(), 2, '0')
            ].join('.');
        }

        function isLeapYear(year) {//是否是闰年
            var a1 = year % 4 == 0;
            var a2 = year % 100 != 0;
            var a3 = year % 400 == 0;
            return (a1 && a2) || a3;
        }
        function showControl(fenqiType, payCutFeeRatio, handRate, payRate, resultObj) {
            if (payCutFeeRatio && payCutFeeRatio != 0) {
                if (payRate && payRate != 0) {
                    resultObj.isShowPayCutFee = true;
                } else {
                    resultObj.isShowPayCutFee = false;
                }
                if (handRate && handRate != 0) {
                    if (fenqiType == 0 || fenqiType == 2) {
                        resultObj.isShowHandFee = false;
                    } else {
                        resultObj.isShowHandFee = true;
                    }
                } else {
                    resultObj.isShowHandFee = false;
                }

            } else {
                switch (fenqiType) {
                    case 0:
                        resultObj.isShowHandFee = false;
                        resultObj.isShowPayCutFee = false;
                        break;
                    case 1:
                        if (handRate && handRate != 0) {
                            resultObj.isShowHandFee = true;
                        } else {
                            resultObj.isShowHandFee = false;
                        }
                        resultObj.isShowPayCutFee = false;
                        break;
                    case 2:
                        resultObj.isShowHandFee = false;
                        if (payRate && payRate != 0) {
                            resultObj.isShowPayCutFee = true;
                        } else {
                            resultObj.isShowPayCutFee = false;
                        }
                        break;
                    default:
                        if (handRate && handRate != 0) {
                            resultObj.isShowHandFee = true;
                        } else {
                            resultObj.isShowHandFee = false;
                        }
                        if (payRate && payRate != 0) {
                            resultObj.isShowPayCutFee = true;
                        } else {
                            resultObj.isShowPayCutFee = false;
                        }
                        break;
                }
            }
            //mPayList
            var list = resultObj.mPayList;
            list.map(function (obj) {
                if (obj.serviceCharge) {
                    if (obj.serviceCharge == 0 || obj.serviceCharge == 0.00) {
                        obj.isShowServiceCharge = false;
                    } else {
                        obj.isShowServiceCharge = true;
                    }
                } else {
                    obj.isShowServiceCharge = false;
                }
                if (obj.guaranteeFee) {
                    if (obj.guaranteeFee == 0 || obj.guaranteeFee == 0.00) {
                        obj.isShowGuaranteeFee = false;
                    } else {
                        obj.isShowGuaranteeFee = true;
                    }
                } else {
                    obj.isShowGuaranteeFee = false;
                }
            })
        }
        function attributeTurnToString(obj) {
            for (prop in obj) {
                if (typeof obj[prop] == 'number') {
                    if (prop != "FeeType" && prop != "payMonth" && prop != "isShowHandFee" && prop != "isShowPayCutFee" && prop != "MonthRate" && prop != "num") {
                        obj[prop] = obj[prop].toFixed(2);
                        obj[prop] = '￥' + obj[prop];
                        if (prop == "handFee" || prop == "payCutFee") {
                            obj[prop] = "-" + obj[prop]
                        }
                    } else {
                        obj[prop] = obj[prop] + "";
                    }

                } else if (Object.prototype.toString.call(obj[prop]) == '[object Array]') {
                    obj[prop].map(function (item) { attributeTurnToString(item) });
                }
            }
        }

        function calresult() {//入口
            var obj = JSON.parse(arguments[0]);
            var
                amount = obj.amount || 0,
                month = obj.Month || 0,
                yearRate = obj.YearRate || 0,
                handRate = obj.HandRate || 0,
                payRate = obj.PayRate || 0,
                payType = obj.PayType || 0,
                isPay = payType,//如果payType==1 isPay=true 如果payType==2 isPay=false
                fenqiType = obj.FenQiType || 0,
                clientCode = obj.ClientCode || 0,//useless
                payCutFeeRatio = obj.PayFeeCut || 0,
                topNum = obj.TopStagingNum || 0,
                payNum = obj.PayTopStagingNum || 0,
                couponValue = obj.couponValue || 0;
            var resultObj = PpdRate.calfee(amount, month, yearRate, handRate, payRate, payType, isPay, fenqiType, clientCode, payCutFeeRatio, topNum, payNum);

            resultObj.firstTotal = "首期 ￥" + resultObj.mPayList[0].total;
            resultObj.firstTotalLabel = "还款计划";
            //控制展示
            showControl(fenqiType, payCutFeeRatio, handRate, payRate, resultObj);
            PpdRate.correctPenny(amount, resultObj);

            //使用优惠券
            couponValue = PpdRate.formatNum2(couponValue).toFixed(2);
            var balance = PpdRate.formatNum2(resultObj.balance).toFixed(2);
            resultObj.balance = "￥" + PpdRate.formatNum2(ComputeObj.add(couponValue, resultObj.balance)).toFixed(2);
            resultObj.balanceOutGray = (couponValue != 0) ? ("￥" + PpdRate.formatNum2(balance).toFixed(2) + "+" + PpdRate.formatNum2(couponValue).toFixed(2)) : ("￥" + PpdRate.formatNum2(balance).toFixed(2));
            attributeTurnToString(resultObj);
            var result = JSON.stringify(resultObj);
            console.log(result);
            return result;
        }

        function calforios() {
            var r = calresult.apply(this, arguments);
            r = encodeURIComponent(r);
            window.location.href = 'objc:doFunc2:' + r;
        }

        function calforandroid() {
            var r = calresult.apply(this, arguments);
            window.ppdai.cbkrate(r);
        }
    </script>
</body>

</html>
